/*
 * Copyright (c) 2006-2021, RT-Thread Development Team
 *
 * SPDX-License-Identifier: Apache-2.0
 *
 * Change Logs:
 * Date           Author       Notes
 * 2023-03-13     白给王       the first version
 */
#include "CAN/common.hpp"

#define LOG_TAG     "CAN.common"
#include <ulog.h>

static struct rt_semaphore can_sem; /* 用于接收消息的信号量 */
static rt_device_t can_dev; /* CAN 设备句柄 */

/* 接收数据回调函数 */
static rt_err_t can_rx_call(rt_device_t dev, rt_size_t size) {
    rt_sem_release(&can_sem);
    return RT_EOK;
}

/* CAN数据接收线程函数 */
static void can_rx_thread(void *parameter) {
    struct rt_can_msg rxmsg = { 0 };

    /* 设置接收回调函数 */
    rt_device_set_rx_indicate(can_dev, can_rx_call);

    while (1) {
        rxmsg.hdr = -1;
        rt_sem_take(&can_sem, RT_WAITING_FOREVER);
        rt_device_read(can_dev, 0, &rxmsg, sizeof(rxmsg));
        LOG_D("Receive ID:%x %2x %2x %2x %2x %2x %2x %2x %2x", rxmsg.id, rxmsg.data[0], rxmsg.data[1], rxmsg.data[2],
                rxmsg.data[3], rxmsg.data[4], rxmsg.data[5], rxmsg.data[6], rxmsg.data[7]);
    }
}

rt_bool_t can_send(struct rt_can_msg msg) {
    rt_bool_t result = RT_FALSE;
    rt_size_t size;

    size = rt_device_write(can_dev, 0, &msg, sizeof(msg));

    if (size != 0) {
        result = RT_TRUE;
        LOG_D("Send ID:%x %2x %2x %2x %2x %2x %2x %2x %2x Successful!", msg.id, msg.data[0], msg.data[1], msg.data[2],
                msg.data[3], msg.data[4], msg.data[5], msg.data[6], msg.data[7]);
    } else {
        result = RT_FALSE;
        LOG_D("Send ID:%x %2x %2x %2x %2x %2x %2x %2x %2x Failed!", msg.id, msg.data[0], msg.data[1], msg.data[2],
                msg.data[3], msg.data[4], msg.data[5], msg.data[6], msg.data[7]);
    }
    return result;
}

int can_init() {
    /* 查找 CAN 设备 */
    can_dev = rt_device_find(CAN_DEV_NAME);
    if (!can_dev) {
        LOG_W("find %s failed!\n", CAN_DEV_NAME);
        return RT_ERROR;
    }

#ifdef RT_CAN_USING_HDR
    struct rt_can_filter_item items[5] = {
    RT_CAN_FILTER_ITEM_INIT(0x701, RT_CAN_STDID, 0, 1, 0x7ff, RT_NULL, RT_NULL),
    RT_CAN_FILTER_ITEM_INIT(0x901, RT_CAN_EXTID, 0, 1, 0x7ff, RT_NULL, RT_NULL) };
    /* 一共有 5 个过滤表 */
    struct rt_can_filter_config cfg = { 2, 1, items };
    /* 设置硬件过滤表 */
    rt_device_control(can_dev, RT_CAN_CMD_SET_FILTER, &cfg);
#endif

    /* 初始化 CAN 接收信号量 */
    rt_sem_init(&can_sem, "can_sem", 0, RT_IPC_FLAG_FIFO);

    /* 以中断接收及发送方式打开 CAN 设备 */
    rt_err_t res = rt_device_open(can_dev, RT_DEVICE_FLAG_INT_TX | RT_DEVICE_FLAG_INT_RX);
    RT_ASSERT(res == RT_EOK);

    /* 创建数据接收线程 */
    rt_thread_t rx_thread = rt_thread_create("can_rx_thread", can_rx_thread, RT_NULL, 4096, 2, 5);
    if (rx_thread != RT_NULL) {
        rt_thread_startup(rx_thread);
    } else {
        LOG_W("create can_rx thread failed!\n");
    }

    return RT_EOK;
}
INIT_APP_EXPORT(can_init);
